﻿CREATE SCHEMA pca_global;

CREATE OR REPLACE FUNCTION pca_global.fn_get_strserienumero(integer,--serie $1
							      integer--numero $2
							      )RETURNS varchar AS
$$
BEGIN
	RETURN (substring(('000'||$1::varchar) FROM (('000'||$1::varchar).length - 2) FOR 3 ))||
	'-'||
	(substring(('000000'||$2::varchar) FROM (('000000'||$2::varchar).length- 5 ) FOR 6));
END;
$$
LANGUAGE plpgsql;

CREATE OR REPLACE FUNCTION pca_global.fn_get_strserienumero(varchar --varciable en formato serie-numero
							     )RETURNS varchar AS
$$
DECLARE
	array_serie_numero text[2];
	resul varchar;
BEGIN
	array_serie_numero := regexp_split_to_array($1,'-');
	resul := pca_global.fn_get_strserienumero(array_serie_numero[1]::integer,array_serie_numero[2]::integer);

	IF(resul<>'')THEN
		RETURN resul;
	ELSE
		RETURN $1;
	END IF;
EXCEPTION
	WHEN invalid_text_representation THEN
		RAISE EXCEPTION 'la cadena "%" no cumple con el formato serie-numero consulte al administrador',$1;
END;
$$
LANGUAGE plpgsql;

CREATE OR REPLACE FUNCTION pca_global.fn_get_strperiodonumero(integer,--serie $1
							      integer--numero $2
							      )RETURNS varchar AS
$$
BEGIN
	RETURN (substring(('00'||$1::varchar) FROM (('00'||$1::varchar).length - 1) FOR 2 ))||
	'-'||
	(substring(('000000'||$2::varchar) FROM (('000000'||$2::varchar).length- 5 ) FOR 6));
END;
$$
LANGUAGE plpgsql;

CREATE OR REPLACE FUNCTION pca_global.fn_get_strperiodonumero(varchar --varciable en formato serie-numero
							     )RETURNS varchar AS
$$
DECLARE
	array_serie_numero text[2];
	resul varchar;
BEGIN
	array_serie_numero := regexp_split_to_array($1,'-');
	resul := pca_global.fn_get_strperiodonumero(array_serie_numero[1]::integer,array_serie_numero[2]::integer);

	IF(resul<>'')THEN
		RETURN resul;
	ELSE
		RETURN $1;
	END IF;
EXCEPTION
	WHEN invalid_text_representation THEN
		RAISE EXCEPTION 'la cadena "%" no cumple con el formato serie-numero consulte al administrador',$1;
END;
$$
LANGUAGE plpgsql;

--devuelve un valor boolaneo que indica si existe o no una tabla del sistema
CREATE OR REPLACE FUNCTION pca_global.fn_existe_tabla(varchar, --el nombre del esquema
						       varchar --el nombre de la tabla
						       ) RETURNS boolean AS
$$
BEGIN
	IF(NOT EXISTS
		(SELECT 
			table_name 
		FROM 
			information_schema.tables 
		WHERE 
			table_schema=$1 AND 
			table_name = $2
		))THEN
		RETURN false;
	ELSE
		RETURN true;
	END IF;
		
END;
$$
LANGUAGE plpgsql;

--devuelve un valor boolaneo que indica si existe o no una secuencia en el sistema
CREATE OR REPLACE FUNCTION pca_global.fn_existe_secuencia(varchar, --el nombre del esquema
							  varchar --el nombre de la secuencia
						          ) RETURNS boolean AS
$$
BEGIN
	IF(NOT EXISTS
		(SELECT 
			sequence_name 
		FROM 
			information_schema.sequences 
		WHERE 
			sequence_schema=$1 AND 
			sequence_name = $2
		))THEN
		RETURN false;
	ELSE
		RETURN true;
	END IF;
		
END;
$$
LANGUAGE plpgsql;

CREATE OR REPLACE FUNCTION pca_global.fn_isinteger_positive(text --Texto a evaluar
						    )RETURNS boolean AS
$$
DECLARE 
	_resul boolean;
BEGIN
	_resul:=false;
	
	SELECT INTO
		_resul
		($1 ~ '^[0-9]+$');

	RETURN _resul;
END;
$$
LANGUAGE plpgsql;

CREATE OR REPLACE FUNCTION pca_global.fn_pseudo_encrypt_bigint(integer
							)RETURNS bigint AS
$$
DECLARE
	l1 int;
	l2 int;
	r1 int;
	r2 int;
	i int:=0;
BEGIN
	l1:= ($1 >> 16) & 65535;
	r1:= $1 & 65535;

	WHILE i < 3 
	LOOP
		l2 := r1;
		r2 := l1 # ((((1366.0 * r1 + 150889) % 714025) / 714025.0) * 32767)::int;
		l1 := l2;
		r1 := r2;
		i := i + 1;
	END LOOP;
	RETURN ((l1::bigint << 16) + r1);
END;
$$
LANGUAGE plpgsql strict immutable;

CREATE OR REPLACE FUNCTION pca_global.fn_ascii(varchar)RETURNS text AS
$$
BEGIN
	RETURN TRANSLATE($1,
			'áàâãäéèêëíìïóòôõöúùûüÁÀÂÃÄÉÈÊËÍÌÏÓÒÔÕÖÚÙÛÜçÇ',
			'aaaaaeeeeiiiooooouuuuAAAAAEEEEIIIOOOOOUUUUcC');
END;
$$
LANGUAGE plpgsql;

/*
 * devuelve una cadena con la consulta para filtrar datos
 *
 */
CREATE OR REPLACE FUNCTION pca_global.fn_get_strfiltro(filtros varchar[]
					               )RETURNS varchar AS
$$
DECLARE
	i integer;--puntero para recorrer los filtros
	numfiltros integer;--numero de filtros
	strfiltro varchar;--el filtro generado
	tmpfiltro varchar;--el filtro temporal
	tipo varchar;--el tipo de dato a filtrar 'string','date','numeric','boolean'
	comparacion varchar;--la comparacion a hacer gt: 'mayor que',lt: 'menor que',eq: 'igual a', df: 'diferente'
	valor varchar;--el filtro
	campo varchar;--el nombre del campo a filtrar
BEGIN
	IF(array_upper(filtros,2)<>4)THEN
		RAISE EXCEPTION 'El parametro "filtros" no es valido';
	ELSE
		numfiltros := array_upper(filtros,1);
		i := 1;
		strfiltro := '';
		WHILE i <= numfiltros 
		LOOP
			tipo := trim(both ' ' from filtros[i][1]);
			comparacion := trim(both ' ' from filtros[i][2]);
			valor := trim(both ' ' from filtros[i][3]);
			campo := trim(both ' ' from filtros[i][4]);
							
			IF(tipo='string')THEN
				IF(comparacion='eq')THEN
					tmpfiltro := quote_ident(campo) || ' = '|| quote_literal(valor);
				ELSIF(comparacion='df')THEN
					tmpfiltro := quote_ident(campo) || ' <> '|| quote_literal(valor);
				ELSE --por defecto like
					tmpfiltro := 'lower(pca_global.fn_ascii(' || quote_ident(campo) 
						     || ')) LIKE '
						     || quote_literal('%' || lower(pca_global.fn_ascii(valor)) || '%');
				END IF;				
			ELSIF(tipo='date')THEN		
				IF(comparacion='gt')THEN
					tmpfiltro := quote_ident(campo)|| '::date' || ' > '|| quote_literal(valor) || '::date';
				ELSIF(comparacion='lt')THEN
					tmpfiltro := quote_ident(campo)|| '::date' || ' < '|| quote_literal(valor) || '::date';
				ELSIF(comparacion='eq')THEN
					tmpfiltro := quote_ident(campo)|| '::date' || ' = '|| quote_literal(valor) || '::date';
				ELSIF(comparacion='df')THEN
					tmpfiltro := quote_ident(campo)|| '::date' || ' <> '|| quote_literal(valor) || '::date';
				ELSE
					RAISE EXCEPTION 'fn_get_strfiltro : comparacion no valida para el tipo date';
				END IF;
			ELSIF(tipo='numeric')THEN
				IF(comparacion='gt')THEN
					tmpfiltro := quote_ident(campo) || ' > '|| valor::numeric;
				ELSIF(comparacion='lt')THEN
					tmpfiltro := quote_ident(campo) || ' < '|| valor::numeric;
				ELSIF(comparacion='eq')THEN
					tmpfiltro := quote_ident(campo) || ' = '|| valor::numeric;
				ELSIF(comparacion='df')THEN
					tmpfiltro := quote_ident(campo) || ' <> '|| valor::numeric;
				ELSE
					RAISE EXCEPTION 'fn_get_strfiltro : comparacion no valida para el tipo numeric';
				END IF;
			ELSIF(tipo='boolean')THEN
				IF(valor='true'|| valor='false')THEN
					tmpfiltro := quote_ident(campo) || ' = '|| valor;
				ELSE
					RAISE EXCEPTION 'fn_get_strfiltro : valor no valido para el tipo boolean';
				END IF;
			ELSE
				RAISE EXCEPTION 'fn_get_strfiltro : Tipo de campo no valido';
			END IF;
			
			strfiltro := strfiltro || tmpfiltro;

			IF(i < numfiltros) THEN
				strfiltro := strfiltro || ' AND ';
			END IF;
			i = i + 1;
		END LOOP;

		RETURN strfiltro;
	END IF;
END;
$$
LANGUAGE plpgsql;


